﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ColorPane
{
    public partial class ColorPicker : Form
    {
        [DllImport("user32.dll")]
        public static extern IntPtr LoadCursorFromFile(string filename);

        public ColorPicker()
        {
            InitializeComponent();
            pnlColorNew.GetType().InvokeMember("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod, null, pnlColorNew, new object[] { ControlStyles.Selectable | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true });
            UpdateColors(csSampler);
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            Properties.Settings.Default.Save();
        }

        private void OptionChekedChanged(object sender, EventArgs e)
        {
            if (sender == null || !(sender is RadioButton)) return;
            RadioButton rb = sender as RadioButton;
            if (!rb.Checked) return;
            csSampler.AlphaSelect = optAlpha.Checked;
            switch (rb.Name)
            {
                case "optAlpha":
                    //csSampler.AlphaSelect = true;
                    break;
                case "optRed":
                    csSampler.ColorTableType = ColorTableType.Red;
                    cdSampler.ColorTableType = ColorTableType.Red;
                    break;
                case "optGreen":
                    csSampler.ColorTableType = ColorTableType.Green;
                    cdSampler.ColorTableType = ColorTableType.Green;
                    break;
                case "optBlue":
                    csSampler.ColorTableType = ColorTableType.Blue;
                    cdSampler.ColorTableType = ColorTableType.Blue;
                    break;
                case "optHue":
                    csSampler.ColorTableType = ColorTableType.Hue;
                    cdSampler.ColorTableType = ColorTableType.Hue;
                    break;
                case "optSaturation":
                    csSampler.ColorTableType = ColorTableType.Saturation;
                    cdSampler.ColorTableType = ColorTableType.Saturation;
                    break;
                case "optBrightness":
                    csSampler.ColorTableType = ColorTableType.Brightness;
                    cdSampler.ColorTableType = ColorTableType.Brightness;
                    break;
                case "optLabL":
                    csSampler.ColorTableType = ColorTableType.LabL;
                    cdSampler.ColorTableType = ColorTableType.LabL;
                    break;
                case "optLaba":
                    csSampler.ColorTableType = ColorTableType.Laba;
                    cdSampler.ColorTableType = ColorTableType.Laba;
                    break;
                case "optLabb":
                    csSampler.ColorTableType = ColorTableType.Labb;
                    cdSampler.ColorTableType = ColorTableType.Labb;
                    break;
            }
        }

        private void FocusLeave(object sender, EventArgs e)
        {
            TextMouseWheel(sender, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
        }

        private void FocusRecived(object sender, EventArgs e)
        {
            if (sender is TextBox) ((TextBox)sender).SelectAll();
        }

        private void TextBoxClick(object sender, EventArgs e)
        {
            if (sender is TextBox) ((TextBox)sender).SelectAll();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            foreach (Control c in Controls)
            {
                if (c is TextBox)
                {
                    ((Control)c).MouseWheel += new MouseEventHandler(TextMouseWheel);
                }
            }
        }

        private void TextMouseWheel(object sender, MouseEventArgs e)
        {
            if (sender == null || !(sender is TextBox)) return;
            TextBox txt = sender as TextBox;
            string[] str = txt.Tag.ToString().Split(';');
            int min = int.Parse(str[0]); int max = int.Parse(str[1]);
            int val;
            bool ok = int.TryParse(txt.Text, out val);
            if (!ok)
            {
                MessageBox.Show(string.Format("Ҫ��{0}��{1}֮�����ֵ���Ѳ�����ӽ���ֵ��", min, max), "ʰɫ��", MessageBoxButtons.OK, MessageBoxIcon.Information);
                UpdateColors(csSampler);
                return;
            }
            int delta = e.Delta / SystemInformation.MouseWheelScrollDelta;
            if (min <= val + delta && val + delta <= max)
            {
                txt.Text = Convert.ToString(val + delta);
                txt.SelectAll();
                TextBoxValueChanged(txt);
            }
            else
            {
                if (e.Button == MouseButtons.Left)//���ڴ���TextBox��FocusLeave�¼�
                {
                    MessageBox.Show(string.Format("Ҫ��{0}��{1}֮�����ֵ���Ѳ�����ӽ���ֵ��", min, max), "ʰɫ��", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    txt.Text = Convert.ToString(Math.Min(Math.Max(min, val), max));
                    TextBoxValueChanged(txt);
                    return;
                }
            }
        }

        private void TextBoxValueChanged(TextBox sender)
        {
            if (sender == txtHue || sender == txtSaturation || sender == txtBrightness)
            {
                csSampler.HSB = ColorSpace.HSB.FromHSB(Convert.ToSingle(txtAlpha.Text) / 255f, Convert.ToSingle(txtHue.Text) / 360f, Convert.ToSingle(txtSaturation.Text) / 100f, Convert.ToSingle(txtBrightness.Text) / 100f);
                cdSampler.HSB = csSampler.HSB;
                UpdateColors(csSampler, "HSB");
            }
            else if (sender == txtAlpha || sender == txtRed || sender == txtGreen || sender == txtBlue)
            {
                csSampler.RGB = Color.FromArgb(Convert.ToInt32(txtAlpha.Text), Convert.ToInt32(txtRed.Text), Convert.ToInt32(txtGreen.Text), Convert.ToInt32(txtBlue.Text));
                cdSampler.Color = csSampler.RGB;
                UpdateColors(csSampler, "ARGB");
            }
            else if (sender == txtLabL || sender == txtLaba || sender == txtLabb)
            {
                csSampler.Lab = ColorSpace.LAB.FromLAB(Convert.ToSingle(txtAlpha.Text) - 128, Convert.ToSingle(txtLabL.Text), Convert.ToSingle(txtLaba.Text), Convert.ToSingle(txtLabb.Text));
                cdSampler.Lab = csSampler.Lab;
                UpdateColors(csSampler, "Lab");
            }
            else if (sender == txtCmykC || sender == txtCmykM || sender == txtCmykY || sender == txtCmykK)
            {
                ColorSpace.CMYK cmyk = ColorSpace.CMYK.FromCMYK(Convert.ToSingle(txtCmykC.Text) / 100.0, Convert.ToSingle(txtCmykM.Text) / 100.0, Convert.ToSingle(txtCmykY.Text) / 100.0, Convert.ToSingle(txtCmykK.Text) / 100.0);
                csSampler.RGB = ColorSpace.CMYK2RGB(cmyk);
                cdSampler.Color = csSampler.RGB;
                UpdateColors(csSampler, "CMYK");
            }
        }

        private void UpdateColors(ColorSlider s, string trigger)
        {
            if (trigger != "HSB")
            {
                txtHue.Text = Convert.ToInt32(s.HSB.H * 360).ToString();
                txtSaturation.Text = Convert.ToInt32(s.HSB.S * 100).ToString();
                txtBrightness.Text = Convert.ToInt32(s.HSB.B * 100).ToString();
            }
            if (trigger != "ARGB")
            {
                txtAlpha.Text = s.RGB.A.ToString();
                txtRed.Text = s.RGB.R.ToString();
                txtGreen.Text = s.RGB.G.ToString();
                txtBlue.Text = s.RGB.B.ToString();
            }
            if (trigger != "Lab")
            {
                txtLabL.Text = Convert.ToInt32(s.Lab.L).ToString();
                txtLaba.Text = Convert.ToInt32(s.Lab.A).ToString();
                txtLabb.Text = Convert.ToInt32(s.Lab.B).ToString();
            }
            if (trigger != "CMYK")
            {
                ColorSpace.CMYK cmyk = ColorSpace.RGB2CMYK(s.RGB);
                txtCmykC.Text = Convert.ToInt32(cmyk.C * 100).ToString();
                txtCmykM.Text = Convert.ToInt32(cmyk.M * 100).ToString();
                txtCmykY.Text = Convert.ToInt32(cmyk.Y * 100).ToString();
                txtCmykK.Text = Convert.ToInt32(cmyk.K * 100).ToString();
            }
            pnlColorNew.BackColor = s.RGB;
            CheckWebSafeColor(s.RGB);
        }

        private void UpdateColors(ColorSlider s)
        {
            UpdateColors(s, "");
        }

        private void CheckWebSafeColor(Color c)
        {
            pnlWebColor.BackColor = ColorSpace.ToWebSafeColor(c);
            bool safe = ColorSpace.IsWebSafeColor(c);
            pnlWebColor.Visible = !safe;
            lblToWebColor.Visible = !safe;
        }

        private void cdSampler_SliderScroll(object sender, EventArgs e)
        {
            if (optAlpha.Checked || optRed.Checked || optGreen.Checked || optBlue.Checked)
            {
                csSampler.RGB = cdSampler.Color;
            }
            else if (optHue.Checked || optSaturation.Checked || optBrightness.Checked)
            {
                csSampler.HSB = cdSampler.HSB;
            }
            else if (optLabL.Checked || optLaba.Checked || optLabb.Checked)
            {
                csSampler.Lab = cdSampler.Lab;
            }
            UpdateColors(csSampler);
        }

        private void csSampler_SliderScroll(object sender, SliderEventArgs e)
        {
            if (optAlpha.Checked || optRed.Checked || optGreen.Checked || optBlue.Checked)
            {
                cdSampler.Color = csSampler.RGB;
            }
            else if (optHue.Checked || optSaturation.Checked || optBrightness.Checked)
            {
                cdSampler.HSB = csSampler.HSB;
            }
            else if (optLabL.Checked || optLaba.Checked || optLabb.Checked)
            {
                cdSampler.Lab = csSampler.Lab;
            }
            UpdateColors(csSampler);
        }

        private void ToNearestWebSafeColor(object sender, EventArgs e)
        {
            csSampler.RGB = pnlWebColor.BackColor;
            cdSampler.Color = pnlWebColor.BackColor;
            UpdateColors(csSampler);
        }

        #region

        public Color Color
        {
            get { return csSampler.RGB; }
            set
            {
                csSampler.RGB = value;
                cdSampler.Color = value;
                pnlColorOld.BackColor = csSampler.RGB;
                UpdateColors(csSampler);
            }
        }

        public ColorSpace.HSB HSB
        {
            get { return csSampler.HSB; }
            set
            {
                csSampler.HSB = value;
                cdSampler.HSB = value;
                pnlColorOld.BackColor = csSampler.RGB;
                UpdateColors(csSampler);
            }
        }

        public ColorSpace.LAB Lab
        {
            get { return csSampler.Lab; }
            set
            {
                csSampler.Lab = value;
                cdSampler.Lab = value;
                pnlColorOld.BackColor = csSampler.RGB;
                UpdateColors(csSampler);
            }
        }

        public ColorSpace.CMYK CMYK
        {
            get { return ColorSpace.RGB2CMYK(csSampler.RGB); }
            set
            {
                csSampler.RGB = ColorSpace.CMYK2RGB(value);
                cdSampler.Color = csSampler.RGB;
                pnlColorOld.BackColor = csSampler.RGB;
                UpdateColors(csSampler);
            }
        }

        public ColorTableType ColorSampleMode
        {
            get { return csSampler.ColorTableType; }
            set
            {
                //csSampler.ColorTableType = value;
                //cdSampler.ColorTableType = value;
                switch (value)
                {
                    case ColorTableType.Hue:
                        optHue.Checked = true; break;
                    case ColorTableType.Saturation:
                        optSaturation.Checked = true; break;
                    case ColorTableType.Brightness:
                        optBrightness.Checked = true; break;
                    case ColorTableType.Red:
                        optRed.Checked = true; break;
                    case ColorTableType.Green:
                        optGreen.Checked = true; break;
                    case ColorTableType.Blue:
                        optBlue.Checked = true; break;
                    case ColorTableType.LabL:
                        optLabL.Checked = true; break;
                    case ColorTableType.Laba:
                        optLaba.Checked = true; break;
                    case ColorTableType.Labb:
                        optLabb.Checked = true; break;
                    default:
                        throw new NotImplementedException();
                }
            }
        }

        #endregion


        #region

        private void lblScreenColor_MouseDown(object sender, MouseEventArgs e)
        {
            Bitmap bmp = new Bitmap(lblScreenColor.Image.Width * 2, lblScreenColor.Image.Height * 2);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawImageUnscaled(lblScreenColor.Image, new Point(lblScreenColor.Image.Width, 0));
            }
            Cursor cur = new Cursor(bmp.GetHicon());// (new System.IO.MemoryStream(Properties.Resources.Pen));
            bmp.Dispose();
            lblScreenColor.Cursor = cur;
        }

        private void lblScreenColor_MouseMove(object sender, MouseEventArgs e)
        {
            if (lblScreenColor.Capture)
            {
                Bitmap bmp = new Bitmap(1, 1);
                Point p = lblScreenColor.PointToScreen(e.Location);
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.CopyFromScreen(p, Point.Empty, new Size(1, 1));
                }
                csSampler.RGB = bmp.GetPixel(0, 0);
                cdSampler.Color = csSampler.RGB;
                UpdateColors(csSampler);
                bmp.Dispose();
            }
        }

        private void lblScreenColor_MouseUp(object sender, MouseEventArgs e)
        {
            lblScreenColor.Cursor.Dispose();
            lblScreenColor.Cursor = Cursors.Default;
        }

        #endregion

    }
}